/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package clks.shattered;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;



/**
 *
 * @author 10135228
 */
public class shattered implements ActionListener{
    
    //private String verzeichnis = "C:/Documents and Settings/10135228/My Documents/pieces";
    private String verzeichnis = "C:/pieces";
    private int amount = 4800;  //max = 4800
    JPanel drawingArea;
    puzzleBasket myBasket;
    int width = 1604, height = 1204;
    
    static ArrayList<Integer> saveArray;
    static int saveState = -1;
    static int threshold = 750;

    
    @SuppressWarnings("unchecked")
    public shattered() {
        ObjectInputStream in;
        try {
            in = new ObjectInputStream(new FileInputStream("save.data"));
            saveArray = (ArrayList<Integer>)in.readObject();
        } catch (Exception ex) {
            System.out.println("File not found...");
            saveArray = new ArrayList<>();
        }

                
                
                
        BufferedImage[] images = readImages(verzeichnis);

        //checkForBorder(images);
        myBasket = new puzzleBasket(images);
        BufferedImage picture = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = picture.createGraphics();
        g2.setColor(Color.BLACK);
        g2.fillRect(0, 0, width, height);
        g2.setColor(Color.WHITE);
        g2.fillRect(2, 2, width-4, height-4);
        drawingArea = new PicturePanel(picture);
        JFrame saveFrame = new JFrame("Save");
        JButton saveButton = new JButton("Save");
        saveButton.addActionListener(this);
        saveFrame.getContentPane().add(saveButton);
        saveFrame.pack();
        saveFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        saveFrame.setVisible(true);
        saveFrame.setLocation(MouseInfo.getPointerInfo().getLocation());
        createBorder(picture);
        try {
            ImageIO.write(picture, "png", new File("Roma.png"));

    //        BufferedImage cornerpiece = myBasket.getSuitableImage("2222222222", null, null);
    //        new drawPanel(cornerpiece);
    //        new drawPanel(myBasket.getSuitableImage("1331122222", myBasket.getLeftColorArray(cornerpiece,23), null));
    //        
    //        new drawPanel(myBasket.getSuitableImage("2222213331",  null, null));
        } catch (IOException ex) {
            Logger.getLogger(shattered.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private BufferedImage[] readImages(String locString) {
        
        long timeStart = System.currentTimeMillis();
        Path location = Paths.get(locString);
        try{
            DirectoryStream<Path> imageFileStream = Files.newDirectoryStream(location, "*.png");
            BufferedImage[] tempArray = new BufferedImage[amount];
            int i = 0;
            for(Path p : imageFileStream){
                //System.out.println(p.getFileName());
                tempArray[i] = ImageIO.read(p.toUri().toURL());
                i++;
                //System.out.println(i);
                if(i==amount) break;
                
            }
            //new drawPanel(tempArray[0]);
            long timeEnd = System.currentTimeMillis();
            String format = String.format("%%0%dd", 2);  
            long elapsedTime = (timeEnd-timeStart) / 1000;  
            String seconds = String.format(format, elapsedTime % 60);  
            String minutes = String.format(format, (elapsedTime % 3600) / 60);  
            String hours = String.format(format, elapsedTime / 3600);  
            String time =  hours + ":" + minutes + ":" + seconds; 
            System.out.println("Done reading images in "+time);
            return tempArray;
        }catch(IOException e){
            System.err.println("ERROR reading images");
        }
        return null;
    }

    private void checkForBorder(BufferedImage[] images) {
        //checking for top and left border
        int topBorders = 0, leftBorders = 0;
        
        for (int i = 0; i < images.length; i++) {
            BufferedImage currentPic = images[i];
            //System.out.println("processing: "+currentPic);
            //top
            boolean top = true, left = true;

            int color = currentPic.getRGB(7, 3);
            if(color != -1) top = false;
            color = currentPic.getRGB(7, 5);
            if(color == -1) top = false; 
            
            //left
            color = currentPic.getRGB(3, 7);
            if(color != -1)left = false;
            color = currentPic.getRGB(5, 7);
            if(color == -1) left = false;                                       
                       
            
            if(top) topBorders++;
            if(left) leftBorders++;
            if(top&&left) {
                new drawPanel(currentPic);
            }

        }
        System.out.print(topBorders+" top border pieces and ");
        System.out.println(leftBorders+" left border pieces.");
    }

    private void createBorder(BufferedImage picture) {
        BufferedImage tmpImage;
        tmpImage = myBasket.getSuitableImage("2222222222", null, null);
        drawImageToPicture(tmpImage,picture,0,0);                
        System.out.println("Top Border:");
        for (int i = 1; i < 80; i++) {
            tmpImage = myBasket.getSuitableImage(getLeftBorderCode(picture,i*20,0)+"22222", getLeftColors(picture,i*20,0), null);    
            drawImageToPicture(tmpImage, picture, i*20, 0);
            drawingArea.repaint();
        }
        System.out.println("Left Border:");
        for (int i = 1; i < 60; i++) {
            tmpImage = myBasket.getSuitableImage("22222"+getTopBorderCode(picture,0,i*20), null, getTopColors(picture,0,i*20));    
            drawImageToPicture(tmpImage, picture, 0, i*20);
            drawingArea.repaint();
        }
        System.out.println("Inner");
        nextLine:
        for (int i = 1; i < 60; i++) {
            for (int j = 1; j < 80; j++) {
                tmpImage = myBasket.getSuitableImage(getLeftBorderCode(picture, j*20, i*20) +getTopBorderCode(picture,j*20,i*20), getLeftColors(picture, j*20, i*20), getTopColors(picture,j*20,i*20));    
                drawImageToPicture(tmpImage, picture, j*20, i*20);
                drawingArea.repaint();
                System.out.println("Done: "+j+"-"+i);
                if(j==19 && i == 16)
                    threshold=950;
//                if(j==43 && i == 33)
//                    continue nextLine;                
            }            
        }
    }

    private void drawImageToPicture(BufferedImage tmpImage, BufferedImage picture, int x, int y) {
        for (int j = 2; j < 26; j++) {
            for (int k = 2; k < 26; k++) {
                int color = tmpImage.getRGB(j, k);
                if(color!=-1){
                    picture.setRGB(x+j-2, y+k-2, tmpImage.getRGB(j, k));     
                }                               
            }            
        }
    }

    
    private String getLeftBorderCode(BufferedImage currentPic, int x, int y) {
        StringBuilder myBuffer = new StringBuilder("");
        for (int i = 5; i < 19; i+=3) {
        if(currentPic.getRGB(1+x, i+y)==-1){
                myBuffer.append("1");
            }                
            else if(currentPic.getRGB(3+x, i+y)==-1){
                myBuffer.append("2");
            }
            else{
                myBuffer.append("3");
            }
        }
        return myBuffer.toString();
    }
    
    private String getTopBorderCode(BufferedImage currentPic, int x, int y) {
        StringBuilder myBuffer = new StringBuilder("");
        for (int i = 5; i < 19; i+=3) {
        if(currentPic.getRGB(i+x, 1+y)==-1){
                myBuffer.append("1");
            }                
            else if(currentPic.getRGB(i+x, 3+y)==-1){
                myBuffer.append("2");
            }
            else{
                myBuffer.append("3");
            }
        }
        return myBuffer.toString();
    }

    private Integer[] getLeftColors(BufferedImage image, int x, int y) {
        Integer[] tmpArray = new Integer[10];
        Integer[] positionsToGet = new Integer[]{2,3,4,7,10,13,16,19,20,21};
        for (int i = 0; i < positionsToGet.length; i++) {
            tmpArray[i] = image.getRGB(x,positionsToGet[i]+y);
            tmpArray[i]= image.getRGB(x+1,positionsToGet[i]+y);
            //System.out.println(Integer.toHexString(tmpArray[i]));
        }        
        return tmpArray;
    }

    private Integer[] getTopColors(BufferedImage image, int x, int y) {
        Integer[] tmpArray = new Integer[10];
        Integer[] positionsToGet = new Integer[]{2,3,4,7,10,13,16,19,20,21};
        for (int i = 0; i < positionsToGet.length; i++) {
            tmpArray[i] = image.getRGB(x+positionsToGet[i], y+1);  
            //System.out.println(Integer.toHexString(tmpArray[i]));
        }        
        return tmpArray;
    }
    
    
    static public Integer getNextChoice(){
        saveState++;
        if(saveArray.size()<=saveState)
            return -1;
        return saveArray.get(saveState);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        ObjectOutputStream out = null;
        try {
             out = new ObjectOutputStream(new FileOutputStream("save.data"));
             out.writeObject(saveArray);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(shattered.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(shattered.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                Logger.getLogger(shattered.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        
    }


    
}
